module utils.SecurityVerification;

import archttp.HttpRequest : HttpRequest;
import archttp.HttpResponse : HttpResponse;
import archttp.HttpMethod : HttpMethod;
import archttp.HttpStatusCode : HttpStatusCode;
import utils.RespData : RespData;

/** 
* 时间戳验证
*/
void timeStampValidator (HttpRequest req, HttpResponse resp, void delegate() next)
{
    import std.conv : to;
    import std.datetime.systime : Clock;
    import std.json : JSONValue, parseJSON, JSONType;

    auto reqMethod = req.method();
    string reqPath = req.path();

    if (reqPath == "/api/login" || reqPath == "/api/logout")
    {
        next();
        return;
    }

    if (reqMethod == HttpMethod.GET || reqMethod == HttpMethod.DELETE)
    {
        string timeStampStr = req.query("time");
        // 查询参数中没有time字段或无值
        if (timeStampStr == "" || timeStampStr is null)
        {
            resp.code(HttpStatusCode.BAD_REQUEST).json(RespData.newData(400, "错误的请求")).send();
            return;
        }

        // 有time字段
        long timeStamp = to!long(timeStampStr);
        long now = Clock.currTime.toUnixTime();
        if (now - timeStamp > 300)
        {
            resp.code(HttpStatusCode.BAD_REQUEST).json(RespData.newData(400, "错误的请求")).send();
            return;
        }

        next();
    }

    if (reqMethod == HttpMethod.POST || reqMethod == HttpMethod.PUT)
    {
        string reqBodyStr = req.body();
        if (reqBodyStr == "" || reqBodyStr is null)
        {
            resp.code(HttpStatusCode.BAD_REQUEST).json(RespData.newData(400, "错误的请求")).send();
            return;
        }

        JSONValue json = parseJSON(reqBodyStr);
        // json中没有time字段
        if ("time" !in json)
        {
            resp.code(HttpStatusCode.BAD_REQUEST).json(RespData.newData(400, "错误的请求")).send();
            return;
        }

        // json中有time字段
        long time = json["time"].get!long;
        long now = Clock.currTime.toUnixTime();
        if (now - time > 300)
        {
            resp.code(HttpStatusCode.BAD_REQUEST).json(RespData.newData(400, "错误的请求")).send();
            return;
        }

        next();
    }
}

/** 
 * 请求参数签名验证函数
 * Params:
 *   reqParamsStr = 请求参数字符串
 *   sign = 签名
 * Returns: 签名是否有效
 */
bool signValidator (string reqParamsStr, string sign)
{
    import std.digest : toHexString, Order, LetterCase;
    import std.digest.sha : sha256Of;
    import utils.ConstValue : Const;

    if (reqParamsStr.length == 0 || sign is null || sign.length == 0)
    {
        return false;
    }

    ubyte[] sha256Bytes = sha256Of((reqParamsStr ~ Const.signSecretStr));
    string encodedParamsStr = toHexString!(Order.increasing, LetterCase.lower)(sha256Bytes);
    string encodedSign = encodedParamsStr[0 .. 15];
    if (sign == encodedSign)
    {
        return true;
    }

    return false;
}
